Skip to content

Updates to LRO samples for Agent Optimization, Dataset Generation & Evaluator Job - #48343

Merged
dargilco merged 20 commits into
mainfrom
dargilco/update-lro-samples
Aug 4, 2026
Merged

Updates to LRO samples for Agent Optimization, Dataset Generation & Evaluator Job#48343
dargilco merged 20 commits into
mainfrom
dargilco/update-lro-samples

Conversation

@dargilco

@dargilco dargilco commented Jul 29, 2026

Copy link
Copy Markdown
Member

Update LRO sync samples for Agent Optimization, Dataset Generation and Evaluator Jobs to use SDK-internal polling, with observation loop in the sample to print the job status. That observation loop is commented as optional, since you can remove the loop -- and just wait for the result. But there will be no screen spew during that time, so I think it's best to loop and show some progress in the console. The async samples the observation loop does not work for some reason. CoPilot suggested a fix that I don't understand why it should be needed, so this needs further investigation and possible discussion with Kashif. So for the async samples, I omitted the observation loop -- I just await for the job result.

For the Agent Optimization case only, in addition to the above "basic" sample, I also update and kept the sample that shows how the app can do the polling itself by making the "get" calls. Rename the sample to "_job_advanced_app_polling.py" (to distinguish it from the "_job_basic.py" sample). This sample uses the raw_response_hook callback function in order to get the Job ID which is required in order to do the "get" call. We can do the same for the other two LRO operation groups in a different PR if needed.

Still to be done:

  • Write custom pollers such that the Job ID can be easily accessible from the poller. That will eliminate the need to use the raw_response_hook as shown in sample samples\agents\optimization\sample_optimization_job_advanced_app_polling.py and its async equivalent. I'll do that in a separate PR.
  • Potentially add sample(s) to show usage of continuation token to stop the SDK-internal polling, and resume it later by constructing another poller from that token. I opened a work item on this.

Also: there were several samples where in the comments at the top of the sample the "Usage" line that shows how to run it used a file name different than the current file. These were all fixed to show the correct file name.

@dargilco dargilco self-assigned this Jul 29, 2026
Copilot AI balanced review requested due to automatic review settings July 29, 2026 15:41
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
9 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates Azure AI Projects samples to expose standard LRO polling progress and capture service error details.

Changes:

  • Reports polling and terminal statuses.
  • Captures LRO responses for failure messages.
  • Converts optimization polling samples to standard pollers.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py Adds polling for lifecycle and replay jobs.
samples/evaluations/sample_rubric_evaluator_generation_iterate.py Adds polling for iterative generation.
samples/evaluations/sample_rubric_evaluator_generation_basic.py Adds polling for basic generation.
samples/evaluations/sample_rubric_evaluator_generation_all_sources.py Adds polling for multi-source and trace jobs.
samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py Adds polling for fine-tuning trace generation.
samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py Adds polling for evaluation trace generation.
samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py Adds polling for prompt-based generation.
samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py Adds polling for file-based generation.
samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py Adds polling for agent-based generation.
samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py Adds polling for fine-tuning data generation.
samples/agents/optimization/sample_optimization_job_basic.py Updates built-in polling documentation.
samples/agents/optimization/sample_optimization_job_basic_polling.py Replaces manual polling with an LRO poller.
samples/agents/optimization/sample_optimization_job_basic_polling_async.py Replaces async manual polling with an LRO poller.
samples/agents/optimization/sample_optimization_job_basic_async.py Updates async polling documentation.
Comments suppressed due to low confidence (4)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:159

  • When background polling fails, done() only indicates that the poller thread stopped; it does not guarantee a terminal service response. Since this branch never calls result(), it hides the poller's HTTP/transport exception and may claim the replay ended in a stale nonterminal status. Observe and chain that exception before raising the custom message.
    if replay_status.lower() != "succeeded":
        error = latest_replay_lro_response.get("error")
        message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
        raise RuntimeError(f"Replay job ended with status `{replay_status}`: {message}")

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:228

  • done() becomes true if the synchronous poller thread exits on an HTTP/transport exception as well as on normal completion. Because this branch never calls result(), it loses that exception and may misleadingly report a stale nonterminal status. Observe and chain the poller exception before raising the custom message.
            if status.lower() != "succeeded":
                error = latest_lro_response.get("error")

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling.py:117

  • This conversion drops the sample's previous reporting of OptimizationJob.warnings. The LRO returns only OptimizationJobResult, which has no warnings field, so non-fatal service advisories are silently discarded even though the raw terminal job response is already captured. Preserve and print its warnings before moving on to the result.
    result = poller.result()

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:124

  • This conversion drops the sample's previous reporting of OptimizationJob.warnings. The LRO returns only OptimizationJobResult, which has no warnings field, so non-fatal service advisories are silently discarded even though the raw terminal job response is already captured. Preserve and print its warnings before moving on to the result.
        result = await result_task

Copilot AI review requested due to automatic review settings July 29, 2026 16:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (16)

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:107

  • If the polling coroutine raises (for example, when the service reports Failed or Canceled), AsyncLROPoller.wait() exits before setting its internal _done flag. The task is then complete with an exception, but this loop continues forever and never reaches the code that awaits and wraps that exception. Poll the task's completion instead.
        while not poller.done():

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:153

  • This replay loop also only observes a sync LROPoller whose Azure Core background thread is doing the actual polling, so it does not restore application-managed polling as described. Disable SDK polling and explicitly fetch the replay job status instead.
    while not replay_poller.done():
        print(f"Replay job status: {replay_poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:224

  • This traces loop likewise only watches a sync LROPoller while its Azure Core background thread performs the requests. It does not demonstrate polling outside the SDK as described. Disable SDK polling and explicitly fetch the traces job status.
            while not poller.done():
                print(f"Traces job status: {poller.status()}")
                time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:14

  • The continuation text is over-indented relative to the bullet, so the rendered sample description no longer aligns with the other list entries.
                returns `LROPoller[EvaluatorVersion]`, whose status is reported until
                the job reaches a terminal state.

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:137

  • This loop only observes the sync LROPoller; constructing that poller has already started Azure Core's background polling thread. It therefore does not demonstrate the application-managed polling described in the PR. Disable SDK polling and explicitly fetch the generation job status if this sample is meant to restore polling outside the SDK.

This issue also appears on line 151 of the same file.

    while not poller.done():
        print(f"Generation job status: {poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:110

  • A sync LROPoller begins polling on an Azure Core background thread as soon as it is constructed; this loop merely reports that thread's status. Consequently this sample still uses SDK polling rather than the application-managed polling promised by the PR description. Disable SDK polling and explicitly retrieve the job status.
    while not poller.done():
        print(f"Generation job status: {poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:134

  • A sync LROPoller starts Azure Core's polling thread during construction, so this loop only observes SDK polling; it does not perform polling outside the SDK as the PR description says. Disable SDK polling and explicitly retrieve the generation job status for an application-polling example.
    while not poller.done():
        print(f"Generation job status: {poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:156

  • This loop only monitors a sync LROPoller; Azure Core starts a background polling thread when that poller is constructed. The sample therefore still relies on SDK polling instead of demonstrating the application-managed polling stated in the PR description. Disable SDK polling and fetch the multi-source job status explicitly.

This issue also appears on line 222 of the same file.

        while not poller.done():
            print(f"Multi-source job status: {poller.status()}")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:177

  • Constructing this sync LROPoller already starts Azure Core's polling thread, so this loop merely reports SDK-managed polling. That contradicts the PR's stated goal of restoring polling outside the SDK. Disable SDK polling and explicitly fetch the data-generation job status.
                while not poller.done():
                    print(f"Data generation job status: {poller.status()}")
                    time.sleep(POLL_INTERVAL_SECONDS)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:174

  • Constructing this sync LROPoller already starts Azure Core's polling thread, so this loop merely reports SDK-managed polling. That contradicts the PR's stated goal of restoring polling outside the SDK. Disable SDK polling and explicitly fetch the data-generation job status.
                while not poller.done():
                    print(f"Data generation job status: {poller.status()}")
                    time.sleep(POLL_INTERVAL_SECONDS)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:138

  • This loop does not itself poll the service: the sync LROPoller started an Azure Core background polling thread when it was created. The sample therefore still demonstrates SDK polling, contrary to the PR description's application-polling goal. Disable SDK polling and explicitly retrieve the job status.
        while not poller.done():
            print(f"Data generation job status: {poller.status()}")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:200

  • This loop does not itself poll the service: the sync LROPoller started an Azure Core background polling thread when it was created. The sample therefore still demonstrates SDK polling, contrary to the PR description's application-polling goal. Disable SDK polling and explicitly retrieve the job status.
    while not poller.done():
        print(f"Data generation job status: {poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:180

  • This loop only observes the sync LROPoller; Azure Core is already polling in its background thread. As written, the sample does not restore application-managed polling as claimed in the PR description. Disable SDK polling and explicitly retrieve the data-generation job status.
        while not poller.done():
            print(f"Data generation job status: {poller.status()}")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:189

  • The sync LROPoller starts Azure Core's background polling thread during construction, so this loop only reports SDK polling. It does not implement the application-managed polling described by the PR. Disable SDK polling and explicitly fetch the fine-tuning generation job status.
    while not poller.done():
        print(f"Data generation job status: {poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling.py:106

  • This loop only monitors the sync LROPoller; Azure Core has already started polling on a background thread. The change therefore replaces the prior application-managed job polling with SDK polling, opposite to the PR description. Keep polling disabled and explicitly call get_optimization_job until terminal.
    while not poller.done():
        print(f"Optimization job status: {poller.status()}")
        time.sleep(poll_interval)

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:109

  • Creating a task from poller.result() explicitly starts Azure Core's async polling loop; the surrounding loop only observes it. This changes the previous application-managed optimization-job polling into SDK-managed polling, contrary to the PR description. Keep SDK polling disabled and explicitly retrieve the job status.
        result_task = asyncio.create_task(poller.result())
        while not poller.done():
            print(f"Optimization job status: {poller.status()}")
            await asyncio.sleep(poll_interval)

@github-actions

This comment has been minimized.

Copilot AI review requested due to automatic review settings July 29, 2026 17:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (16)

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:109

  • AsyncLROPoller.done() is set only after wait() returns successfully. If the LRO fails, result_task completes with an exception but poller.done() remains false, so this loop sleeps forever and the failure handling below is never reached. Use the task's completion state as the loop condition.
        result_task = asyncio.create_task(poller.result())
        while not poller.done():
            print(f"Optimization job status: {poller.status()}")
            await asyncio.sleep(poll_interval)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:14

  • The added indentation makes these continuation lines render far to the right of the surrounding bullet text instead of aligning with it.
                returns `LROPoller[EvaluatorVersion]`, whose status is reported until
                the job reaches a terminal state.

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:153

  • This replay loop also only observes the synchronous LROPoller's background SDK polling; calling done() does not perform an application poll. It therefore does not demonstrate the application-managed polling promised by the PR.
    while not replay_poller.done():
        print(f"Replay job status: {replay_poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:224

  • This second synchronous loop likewise only observes the LROPoller's background SDK polling. It does not issue application-level status requests and therefore does not demonstrate the polling mode described in the PR.
            while not poller.done():
                print(f"Traces job status: {poller.status()}")
                time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:137

  • This does not implement the application-managed polling described by the PR. A synchronous LROPoller starts its SDK polling thread during construction (azure-core/.../_poller.py:228-240), so done() and status() only observe SDK-managed polling. Use polling=False plus explicit get_generation_job calls between sleeps, or revise the sample's stated purpose.

This issue also appears on line 151 of the same file.

    while not poller.done():
        print(f"Generation job status: {poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:110

  • A synchronous LROPoller begins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; use polling=False and explicit status retrieval between sleeps.
    while not poller.done():
        print(f"Generation job status: {poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:134

  • A synchronous LROPoller begins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; use polling=False and explicit status retrieval between sleeps.
    while not poller.done():
        print(f"Generation job status: {poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:156

  • A synchronous LROPoller begins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; use polling=False and explicit status retrieval between sleeps.

This issue also appears on line 222 of the same file.

        while not poller.done():
            print(f"Multi-source job status: {poller.status()}")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:177

  • A synchronous LROPoller begins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; use polling=False and explicit status retrieval between sleeps.
                while not poller.done():
                    print(f"Data generation job status: {poller.status()}")
                    time.sleep(POLL_INTERVAL_SECONDS)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:174

  • A synchronous LROPoller begins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; use polling=False and explicit status retrieval between sleeps.
                while not poller.done():
                    print(f"Data generation job status: {poller.status()}")
                    time.sleep(POLL_INTERVAL_SECONDS)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:138

  • A synchronous LROPoller begins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; use polling=False and explicit status retrieval between sleeps.
        while not poller.done():
            print(f"Data generation job status: {poller.status()}")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:200

  • A synchronous LROPoller begins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; use polling=False and explicit status retrieval between sleeps.
    while not poller.done():
        print(f"Data generation job status: {poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:180

  • A synchronous LROPoller begins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; use polling=False and explicit status retrieval between sleeps.
        while not poller.done():
            print(f"Data generation job status: {poller.status()}")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:189

  • A synchronous LROPoller begins SDK polling in a background thread as soon as it is created (azure-core/.../_poller.py:228-240). This loop only observes that thread, so it does not restore the application-managed polling described by the PR; use polling=False and explicit status retrieval between sleeps.
    while not poller.done():
        print(f"Data generation job status: {poller.status()}")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling.py:106

  • This replaces the prior polling=False plus get_optimization_job application polling with the default synchronous LROPoller, which starts SDK polling in a background thread during construction. The loop therefore only observes SDK polling and makes this sample another built-in-polling example, contrary to the PR's stated separation between the basic and polling samples.
    while not poller.done():
        print(f"Optimization job status: {poller.status()}")
        time.sleep(poll_interval)

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:109

  • Creating a task for poller.result() starts the async SDK polling loop (azure-core/.../_async_poller.py:230-258); the surrounding loop merely reports its status. This converts the polling sample into another SDK-managed-polling example instead of preserving the application-managed polling that the PR description says should remain distinct.
        result_task = asyncio.create_task(poller.result())
        while not poller.done():
            print(f"Optimization job status: {poller.status()}")
            await asyncio.sleep(poll_interval)

@github-actions

This comment has been minimized.

Copilot AI review requested due to automatic review settings July 29, 2026 18:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (28)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:130

  • The replay call also leaves polling=True, so this second synchronous LROPoller starts another SDK polling thread immediately. The subsequent done()/status() loop observes SDK polling rather than performing the application-controlled polling described by the PR.
    replay_poller = project_client.beta.evaluators.begin_create_generation_job(
        job=job_body,
        operation_id=operation_id,
        polling_interval=poll_interval_seconds,
        raw_response_hook=capture_replay_lro_response,

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:197

  • The traces path likewise leaves SDK polling enabled. The synchronous LROPoller starts polling as soon as it is constructed, so this path only reports SDK-managed progress instead of demonstrating application-controlled polling.
            poller = project_client.beta.evaluators.begin_create_generation_job(

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:143

  • done() also becomes true when the background polling thread exits with an exception (azure/core/polling/_poller.py:242-261). If a polling request fails while the status is still InProgress, this branch masks the stored SDK exception as “ended with status InProgress: ”; only result()/wait() propagates the original exception. Surface the poller exception before interpreting a non-success status.
    if status.lower() != "succeeded":
        error = latest_lro_response.get("error")
        message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
        raise RuntimeError(f"Generation job ended with status `{status}`: {message}")

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:116

  • done() is also true when the polling thread exits with an exception. If a request fails while status remains InProgress, this branch masks the stored SDK exception with “ended with status InProgress”; result() is the call that would propagate the real failure.
    if status.lower() != "succeeded":
        error = latest_lro_response.get("error")
        message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
        raise RuntimeError(f"Generation job ended with status `{status}`: {message}")

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:159

  • The replay loop has the same exception path: done() is true after the polling thread fails, while status() may still be InProgress. Raising this custom error before calling result() masks the underlying SDK polling exception and reports a false terminal status.
    if replay_status.lower() != "succeeded":
        error = latest_replay_lro_response.get("error")
        message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
        raise RuntimeError(f"Replay job ended with status `{replay_status}`: {message}")

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:140

  • done() is also true when the polling thread exits with an exception. If a request fails while status remains InProgress, this branch masks the stored SDK exception with “ended with status InProgress”; result() is the call that would propagate the real failure.
    if status.lower() != "succeeded":
        error = latest_lro_response.get("error")
        message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
        raise RuntimeError(f"Generation job ended with status `{status}`: {message}")

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:162

  • A failed polling thread also makes done() true. When a request exception leaves status as InProgress, this branch replaces the stored SDK exception with a misleading terminal-status RuntimeError; calling result() is what propagates the actual polling failure.
        if status.lower() != "succeeded":
            error = latest_lro_response.get("error")
            message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
            raise RuntimeError(f"Multi-source job ended with status `{status}`: {message}")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:144

  • done() is also true after the polling thread fails. If the failure occurs while status remains InProgress, this branch masks the stored SDK exception with a false terminal-status error; result() would otherwise propagate the actual polling failure.
        if status.lower() != "succeeded":
            error = latest_lro_response.get("error")
            message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
            raise RuntimeError(f"Data generation job ended with status `{status}`: {message}")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:206

  • done() is also true after the polling thread fails. If the failure occurs while status remains InProgress, this branch masks the stored SDK exception with a false terminal-status error; result() would otherwise propagate the actual polling failure.
    if status.lower() != "succeeded":
        error = latest_lro_response.get("error")
        message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
        raise RuntimeError(f"Data generation job ended with status `{status}`: {message}")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:186

  • done() is also true after the polling thread fails. If the failure occurs while status remains InProgress, this branch masks the stored SDK exception with a false terminal-status error; result() would otherwise propagate the actual polling failure.
        if status.lower() != "succeeded":
            error = latest_lro_response.get("error")
            message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
            raise RuntimeError(f"Data generation job ended with status `{status}`: {message}")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:195

  • done() is also true after the polling thread fails. If the failure occurs while status remains InProgress, this branch masks the stored SDK exception with a false terminal-status error; result() would otherwise propagate the actual polling failure.
    if status.lower() != "succeeded":
        error = latest_lro_response.get("error")
        message = error.get("message", "<no error message>") if isinstance(error, dict) else "<no error message>"
        raise RuntimeError(f"Data generation job ended with status `{status}`: {message}")

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:14

  • These continuation lines are over-indented relative to the surrounding bullet list, so the module description renders as a malformed list item.
                returns `LROPoller[EvaluatorVersion]`, whose status is reported until
                the job reaches a terminal state.

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:228

  • A failed polling thread also makes done() true. When a request exception leaves status as InProgress, this branch replaces the stored SDK exception with a misleading terminal-status RuntimeError; calling result() is what propagates the actual polling failure.
            if status.lower() != "succeeded":
                error = latest_lro_response.get("error")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:181

  • done() becomes true when polling exits with an exception as well as on service completion. If a polling request fails while status is still InProgress, this branch masks the SDK exception as a misleading terminal-status error instead of letting result() propagate the real cause.
                if status.lower() != "succeeded":
                    error = latest_lro_response.get("error")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:178

  • done() becomes true when polling exits with an exception as well as on service completion. If a polling request fails while status is still InProgress, this branch masks the SDK exception as a misleading terminal-status error instead of letting result() propagate the real cause.
                if status.lower() != "succeeded":
                    error = latest_lro_response.get("error")

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:111

  • This still uses SDK-managed polling: the default polling=True constructs a synchronous LROPoller, which starts its polling thread immediately (sdk/core/azure-core/azure/core/polling/_poller.py:225-240). done() and status() only observe that background poller, so this does not restore the application-controlled polling described by the PR. Disable SDK polling and fetch job status explicitly, as the optimization polling sample does, or revise the sample's stated purpose.

This issue also appears on line 126 of the same file.

    poller = project_client.beta.evaluators.begin_create_generation_job(
        job=job_body,
        operation_id=operation_id,
        polling_interval=poll_interval_seconds,
        raw_response_hook=capture_lro_response,

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:84

  • This still uses SDK-managed polling: the default synchronous LROPoller starts polling in a background thread at construction (sdk/core/azure-core/azure/core/polling/_poller.py:225-240). The new loop only reports that poller's state, rather than restoring the application-controlled polling described by the PR.
    poller = project_client.beta.evaluators.begin_create_generation_job(

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:101

  • This still uses SDK-managed polling: the default synchronous LROPoller starts polling in a background thread at construction (sdk/core/azure-core/azure/core/polling/_poller.py:225-240). The new loop only reports that poller's state, rather than restoring the application-controlled polling described by the PR.
    poller = project_client.beta.evaluators.begin_create_generation_job(

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:140

  • This call leaves SDK polling enabled. A synchronous LROPoller starts its polling thread immediately (sdk/core/azure-core/azure/core/polling/_poller.py:225-240), so the added done()/status() loop merely observes SDK polling and does not demonstrate the application-controlled polling described by the PR.

This issue also appears on line 197 of the same file.

        poller = project_client.beta.evaluators.begin_create_generation_job(

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:152

  • This call still defaults to SDK polling. The synchronous LROPoller starts a background polling thread on construction (sdk/core/azure-core/azure/core/polling/_poller.py:225-240), so the new loop observes SDK polling rather than performing the application-controlled polling described by the PR.
                poller = project_client.beta.datasets.begin_create_generation_job(

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:151

  • This call still defaults to SDK polling. The synchronous LROPoller starts a background polling thread on construction (sdk/core/azure-core/azure/core/polling/_poller.py:225-240), so the new loop observes SDK polling rather than performing the application-controlled polling described by the PR.
                poller = project_client.beta.datasets.begin_create_generation_job(

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:131

  • This call still defaults to SDK polling. A synchronous LROPoller begins polling in its background thread immediately, and done()/status() only observe it. Therefore this does not demonstrate the application-controlled polling described by the PR.
        poller = project_client.beta.datasets.begin_create_generation_job(

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:167

  • This call still defaults to SDK polling. A synchronous LROPoller begins polling in its background thread immediately, and done()/status() only observe it. Therefore this does not demonstrate the application-controlled polling described by the PR.
    poller = project_client.beta.datasets.begin_create_generation_job(

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:173

  • This call still defaults to SDK polling. A synchronous LROPoller begins polling in its background thread immediately, and done()/status() only observe it. Therefore this does not demonstrate the application-controlled polling described by the PR.
        poller = project_client.beta.datasets.begin_create_generation_job(

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:182

  • This call still defaults to SDK polling. A synchronous LROPoller begins polling in its background thread immediately, and done()/status() only observe it. Therefore this does not demonstrate the application-controlled polling described by the PR.
    poller = project_client.beta.datasets.begin_create_generation_job(

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling.py:10

  • This description says the sample polls the standard LRO, but the implementation passes polling=False and repeatedly calls get_optimization_job; it polls the job resource outside the SDK poller. Keep the description aligned with the behavior.
    optimization job and poll its standard LRO to completion.

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling.py:78

  • response is a PipelineResponse, not an OptimizationJob, as shown by the immediate response.http_response.json() access. The comment gives sample readers the wrong raw-response-hook callback contract.
        # Since `polling=False` is set below, it is guaranteed that `capture_created_job` will be
        # invoked once on the initial "201 Created" response, and `response` is of type `OptimizationJob`.

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_polling_async.py:81

  • response is a PipelineResponse, not an OptimizationJob, as shown by the immediate response.http_response.text() access. The comment gives sample readers the wrong raw-response-hook callback contract.
            # Since `polling=False` is set below, it is guaranteed that `capture_created_job` will be
            # invoked once on the initial "201 Created" response, and `response` is of type `OptimizationJob`.

Copilot AI review requested due to automatic review settings July 29, 2026 18:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Suppressed comments (18)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:114

  • This new async dataset sample is auto-discovered by test_samples_async.py, but unlike its synchronous counterpart it is not excluded and this PR supplies no recording. Playback CI will attempt to execute it without a recording. Add this exact filename to the async dataset samples_to_skip list or commit a usable recording.
async def main() -> None:

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10

  • This description is inaccurate: the code passes polling=False and repeatedly calls get_optimization_job, so it polls the job outside the standard LRO rather than polling the LRO itself.
    sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78
  • response is a pipeline response, not an OptimizationJob—the following lines access response.http_response and deserialize its body into that model. The current type claim misleads readers implementing their own hook.
    sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:30
  • This sample uses begin_create_generation_job, which replaced create_generation_job in azure-ai-projects 2.4.0. Advertising 2.2.0 as the minimum allows installation of versions where this API does not exist.
    pip install "azure-ai-projects>=2.2.0" azure-identity openai python-dotenv aiohttp

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic.py:18

  • The usage command names a file that does not exist, so copying it fails. It should reference this sample's actual filename.
    python sample_optimization_job_app_polling.py

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py:18

  • The usage command names a file that does not exist, so copying it fails. It should reference this sample's actual filename.
    python sample_optimization_job_app_polling_async.py

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:123

  • This GET does not exercise the operation_id idempotent re-submit described in the module documentation; it only retrieves the job by the ID already returned, so the assertion is tautological. Restore a second begin_create_generation_job call with the same operation ID, or remove the idempotency claim and replay terminology.
    replay_job = project_client.beta.evaluators.get_generation_job(evaluator.generation_job_id)
    assert replay_job.id == evaluator.generation_job_id

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:102

  • This still delegates polling to the SDK's background LROPoller; calling done() and status() only observes that SDK polling. The PR description says this sample should demonstrate application polling outside the SDK. Use polling=False, capture the created job ID, and poll get_generation_job to a terminal status instead, leaving .result() as the documented built-in alternative.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        time.sleep(poll_interval_seconds)
        print(f"\tstatus=`{poller.status()}`")

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:148

  • This still delegates polling to the SDK's background LROPoller; calling done() and status() only observes that SDK polling. The PR description says this sample should demonstrate application polling outside the SDK. Use polling=False, capture the created job ID, and poll get_generation_job to a terminal status instead, leaving .result() as the documented built-in alternative.
        # Optional: While SDK is polling, periodically print the job status until the job is complete
        print("Periodically check job status:")
        while not poller.done():
            time.sleep(poll_interval_seconds)
            print(f"\tstatus=`{poller.status()}`")

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:207

  • This second flow also observes the SDK's background polling rather than polling outside the SDK as stated in the PR description. Disable SDK polling, retain the created job ID, and use get_generation_job until a terminal status.
            # Optional: While SDK is polling, periodically print the job status until the job is complete
            print("Periodically check job status:")
            while not poller.done():
                time.sleep(poll_interval_seconds)
                print(f"\tstatus=`{poller.status()}`")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:170

  • This still delegates polling to the SDK's background LROPoller; calling done() and status() only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Use polling=False, capture the created job ID, and poll get_generation_job to a terminal status instead.
                # Optional: While SDK is polling, periodically print the job status until the job is complete
                print("Periodically check job status:")
                while not poller.done():
                    time.sleep(POLL_INTERVAL_SECONDS)
                    print(f"\tstatus=`{poller.status()}`")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:167

  • This still delegates polling to the SDK's background LROPoller; calling done() and status() only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Use polling=False, capture the created job ID, and poll get_generation_job to a terminal status instead.
                # Optional: While SDK is polling, periodically print the job status until the job is complete
                print("Periodically check job status:")
                while not poller.done():
                    time.sleep(POLL_INTERVAL_SECONDS)
                    print(f"\tstatus=`{poller.status()}`")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:130

  • This still delegates polling to the SDK's background LROPoller; calling done() and status() only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Use polling=False, capture the created job ID, and poll get_generation_job to a terminal status instead.
        # Optional: While SDK is polling, periodically print the job status until the job is complete
        print("Periodically check job status:")
        while not poller.done():
            time.sleep(poll_interval_seconds)
            print(f"\tstatus=`{poller.status()}`")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:194

  • This still delegates polling to the SDK's background LROPoller; calling done() and status() only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Use polling=False, capture the created job ID, and poll get_generation_job to a terminal status instead.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        time.sleep(poll_interval_seconds)
        print(f"\tstatus=`{poller.status()}`")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:172

  • This still delegates polling to the SDK's background LROPoller; calling done() and status() only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Use polling=False, capture the created job ID, and poll get_generation_job to a terminal status instead.
        # Optional: While SDK is polling, periodically print the job status until the job is complete
        print("Periodically check job status:")
        while not poller.done():
            time.sleep(poll_interval_seconds)
            print(f"\tstatus=`{poller.status()}`")

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:182

  • This still delegates polling to the SDK's background LROPoller; calling done() and status() only observes that SDK polling. The PR description says dataset samples should demonstrate application polling outside the SDK. Use polling=False, capture the created job ID, and poll get_generation_job to a terminal status instead.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        time.sleep(poll_interval_seconds)
        print(f"\tstatus=`{poller.status()}`")

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:107

  • This still delegates polling to the SDK's background LROPoller; calling done() and status() only observes that SDK polling. The PR description says this sample should demonstrate application polling outside the SDK. Use polling=False, capture the created job ID, and poll get_generation_job to a terminal status instead, leaving .result() as the documented built-in alternative.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        time.sleep(poll_interval_seconds)
        print(f"\tstatus=`{poller.status()}`")

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:126

  • This still delegates polling to the SDK's background LROPoller; calling done() and status() only observes that SDK polling. The PR description says this sample should demonstrate application polling outside the SDK. Use polling=False, capture the created job ID, and poll get_generation_job to a terminal status instead, leaving .result() as the documented built-in alternative.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        time.sleep(poll_interval_seconds)
        print(f"\tstatus=`{poller.status()}`")

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor
[Pilot] PR Pipeline Failure Analysis

A CI pipeline failed on this pull request. Here is an automated analysis of what went wrong and how to get the build green.

What failed

A single async sample test is failing consistently across all platforms (macOS, Ubuntu 3.10/3.13/3.14, Windows) and all package install modes (sdist, whl, mindependency):

  • Test: sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]

This PR adds a new async sample sample_dataset_generation_job_simpleqna_for_finetuning_async.py (per the PR description). The test for that sample is failing on every platform, which points to an issue in the new async sample itself rather than an environment or infrastructure problem.

Recommended next steps

  • Reproduce the failure locally by running:
    pytest sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py -k "test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]" -v
    
  • Review the new async sample file (samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py) for correctness — pay particular attention to the polling logic change introduced in this PR, as the description notes a shift back to application-level polling.
  • Check test recordings: if the test relies on recorded HTTP responses, ensure an up-to-date recording exists for the new async sample.
  • See the CI troubleshooting guide: https://aka.ms/ci-fix
  • Push new commits to address the failures; this comment updates automatically on the next failing run.
Raw pipeline analysis (azsdk ci analyze)
Analyzing pipeline https://github.com/Azure/azure-sdk-for-python/pull/48343...
--------------------------------------------------------------------------------
Failed Tests
--------------------------------------------------------------------------------
{
  "/tmp/6651903/LLM Artifacts - macos311 - 1/ai-azure-ai-projects-test-junit-sdist.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - macos311 - 1/ai-azure-ai-projects-test-junit-mindependency.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - macos311 - 1/ai-azure-ai-projects-test-junit-whl.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - ubuntu2404_310 - 1/ai-azure-ai-projects-test-junit-sdist.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - ubuntu2404_310 - 1/ai-azure-ai-projects-test-junit-mindependency.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - ubuntu2404_310 - 1/ai-azure-ai-projects-test-junit-whl.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - Ubuntu2404_313 - 1/ai-azure-ai-projects-test-junit-sdist.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - Ubuntu2404_313 - 1/ai-azure-ai-projects-test-junit-mindependency.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - Ubuntu2404_313 - 1/ai-azure-ai-projects-test-junit-whl.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - ubuntu2404_310_coverage - 1/ai-azure-ai-projects-test-junit-sdist.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - ubuntu2404_310_coverage - 1/ai-azure-ai-projects-test-junit-mindependency.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - ubuntu2404_310_coverage - 1/ai-azure-ai-projects-test-junit-whl.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - Ubuntu2404_314 - 1/ai-azure-ai-projects-test-junit-sdist.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - Ubuntu2404_314 - 1/ai-azure-ai-projects-test-junit-mindependency.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - Ubuntu2404_314 - 1/ai-azure-ai-projects-test-junit-whl.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - windows2022_312 - 1/ai-azure-ai-projects-test-junit-sdist.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - windows2022_312 - 1/ai-azure-ai-projects-test-junit-mindependency.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ],
  "/tmp/6651903/LLM Artifacts - windows2022_312 - 1/ai-azure-ai-projects-test-junit-whl.xml": [
    "sdk.ai.azure-ai-projects.tests.samples.test_samples_async.TestSamplesAsync.test_datasets_samples[sample_dataset_generation_job_simpleqna_for_finetuning_async]"
  ]
}

Copilot detected the failing pipeline and generated the analysis above. To have it attempt a fix automatically, reply with @copilot please fix the failing pipeline on this PR.

Generated by Pipeline Analysis - Next Steps · 23.6 AIC · ⌖ 9.43 AIC · ⊞ 6.6K ·

Copilot AI review requested due to automatic review settings August 3, 2026 18:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.

Suppressed comments (9)

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py:99

  • AsyncLROPoller does not start polling at construction; its polling method runs only when result()/wait() is awaited. Consequently, done() remains false here and this loop never reaches line 103. Start poller.result() as a task before monitoring it, then await that task for the result.
        # Optional: While SDK is polling, periodically print the job status until the job is complete
        print("Periodically check job status:")
        while not poller.done():
            await asyncio.sleep(poll_interval)
            print(f"status=`{poller.status()}`")

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10

  • This description says the sample polls a standard LRO, but the implementation passes polling=False and manually calls get_optimization_job. Describe the application-managed polling behavior instead.
    sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78
  • response is a pipeline response, not an OptimizationJob; the following response.http_response access also demonstrates this. The comment currently teaches an incorrect callback contract.
    sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:181
  • This default selects only the blocking await poller.result() branch, so the newly added async sample does not demonstrate the application-visible status polling that this PR restores. Default this to true (or remove the branch) so running the sample exercises its advertised polling flow.
        print_poller_status = False

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic.py:18

  • The usage command names a file that does not exist, so copying it fails. It should match this sample's actual filename.
    python sample_optimization_job_app_polling.py

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py:18

  • The usage command names a file that does not exist, so copying it fails. It should match this sample's actual filename.
    python sample_optimization_job_app_polling_async.py

sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:170

  • The new sample is excluded from the repository's auto-discovered async sample suite, so none of its upload, polling, result handling, or cleanup paths execute in CI. Please add the recording and enable the sample rather than merging it permanently untested.
                "sample_dataset_generation_job_simpleqna_for_finetuning_async.py", # Need to add recordings

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:30

  • This minimum version cannot run the sample: begin_create_generation_job was introduced by the 2.4.0 rename/LRO conversion documented in CHANGELOG.md:21. Installing the advertised 2.2.x version leaves only the earlier API.
    pip install "azure-ai-projects>=2.2.0" azure-identity openai python-dotenv aiohttp

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:129

  • After this upload succeeds, any failure while processing the input, creating/polling the job, or inspecting outputs bypasses the deletions at the end of main, leaving Azure OpenAI files behind. Track created IDs and perform best-effort deletion in a finally block so failed sample runs do not leak resources.
        seed_file = await openai_client.files.create(
            file=(seed_filename, io.BytesIO(SEED_REFERENCE_DOCUMENT.encode("utf-8"))),
            purpose="user_data",
        )

Copilot AI review requested due to automatic review settings August 3, 2026 22:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.

Suppressed comments (21)

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10

  • This description says the sample polls a standard LRO, but the implementation passes polling=False and repeatedly calls get_optimization_job; no LRO is being polled. Keep the prior “manually poll” wording so readers understand the application owns service polling.
    sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78
  • response is a PipelineResponse, not an OptimizationJob (the next lines access response.http_response and deserialize the job). The type claim is misleading for readers implementing this hook.
    sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:123
  • This replacement no longer verifies idempotent re-submission: get_generation_job only fetches by ID and never reuses operation_id, despite the sample description advertising idempotent re-submits. Restore the second begin_create_generation_job call with the same operation ID and compare its result, or remove that advertised lifecycle behavior.
    # Retrieve the persisted generation job using the id returned in the LRO result.
    if evaluator.generation_job_id is None:
        raise RuntimeError("The generated evaluator did not include a generation job id.")
    replay_job = project_client.beta.evaluators.get_generation_job(evaluator.generation_job_id)
    assert replay_job.id == evaluator.generation_job_id

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:207

  • This second loop also only observes SDK-owned polling; the background LROPoller performs the service requests. To match the PR's application-polling goal, disable SDK polling and repeatedly retrieve the generation job by ID, or revise the stated scope.
            # Optional: While SDK is polling, periodically print the job status until the job is complete
            print("Periodically check job status:")
            while not poller.done():
                print(f"\tstatus=`{poller.status()}`")
                time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:181

  • The new async sample still uses the blocking SDK-polling pattern that the PR says it is replacing: awaiting poller.result() is what starts and runs AsyncLROPoller polling. Implement application-owned polling (for example, polling=False plus async get_generation_job calls) or clarify that this new sample intentionally demonstrates SDK polling.
        print("Waiting for the dataset generation job to complete.")
        job_result = await poller.result()

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic.py:18

  • The usage command names a file that does not exist, so copying it fails. It should reference this sample's actual filename.
    python sample_optimization_job_app_polling.py

sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:170

  • The newly added sample is explicitly removed from the package's auto-discovered async sample tests, so none of its API usage or cleanup behavior runs in CI. Add the recording and let test_datasets_samples include this file before merging.
                "sample_dataset_generation_job_simpleqna_for_finetuning_async.py",  # Need to add recordings

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py:18

  • The usage command names a file that does not exist, so copying it fails. It should reference this sample's actual filename.
    python sample_optimization_job_app_polling_async.py

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:30

  • This sample uses begin_create_generation_job, which was introduced in 2.4.0 (CHANGELOG.md:19-22), but the installation command permits 2.2.x/2.3.x where that API is unavailable. Raise the documented minimum to 2.4.0.
    pip install "azure-ai-projects>=2.2.0" azure-identity openai python-dotenv aiohttp

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:129

  • After the input file is created, any processing failure, LRO exception, missing output, or retrieval failure exits before lines 209-214, leaking the input and possibly generated files in the user's project. Track created IDs and perform best-effort deletion in finally, as the trace-generation samples do.
        seed_file = await openai_client.files.create(
            file=(seed_filename, io.BytesIO(SEED_REFERENCE_DOCUMENT.encode("utf-8"))),
            purpose="user_data",
        )

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:107

  • This loop only observes SDK-owned polling: synchronous LROPoller starts its polling thread during construction, and done()/status() do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Use polling=False, capture the initial job ID, and call get_generation_job until terminal, or revise the stated scope.

This issue also appears on line 119 of the same file.

    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        print(f"\tstatus=`{poller.status()}`")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:102

  • This loop only observes SDK-owned polling: synchronous LROPoller starts its polling thread during construction, and done()/status() do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Use polling=False, capture the initial job ID, and call get_generation_job until terminal, or revise the stated scope.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        print(f"\tstatus=`{poller.status()}`")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:126

  • This loop only observes SDK-owned polling: synchronous LROPoller starts its polling thread during construction, and done()/status() do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Use polling=False, capture the initial job ID, and call get_generation_job until terminal, or revise the stated scope.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        print(f"\tstatus=`{poller.status()}`")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:148

  • This loop only observes SDK-owned polling: synchronous LROPoller starts its polling thread during construction, and done()/status() do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Use polling=False, capture the initial job ID, and call get_generation_job until terminal, or revise the stated scope.

This issue also appears on line 203 of the same file.

        # Optional: While SDK is polling, periodically print the job status until the job is complete
        print("Periodically check job status:")
        while not poller.done():
            print(f"\tstatus=`{poller.status()}`")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:170

  • This loop only observes SDK-owned polling: synchronous LROPoller starts its polling thread during construction, and done()/status() do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Use polling=False, capture the initial job ID, and call get_generation_job until terminal, or revise the stated scope.
                # Optional: While SDK is polling, periodically print the job status until the job is complete
                print("Periodically check job status:")
                while not poller.done():
                    print(f"\tstatus=`{poller.status()}`")
                    time.sleep(POLL_INTERVAL_SECONDS)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:167

  • This loop only observes SDK-owned polling: synchronous LROPoller starts its polling thread during construction, and done()/status() do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Use polling=False, capture the initial job ID, and call get_generation_job until terminal, or revise the stated scope.
                # Optional: While SDK is polling, periodically print the job status until the job is complete
                print("Periodically check job status:")
                while not poller.done():
                    print(f"\tstatus=`{poller.status()}`")
                    time.sleep(POLL_INTERVAL_SECONDS)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:130

  • This loop only observes SDK-owned polling: synchronous LROPoller starts its polling thread during construction, and done()/status() do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Use polling=False, capture the initial job ID, and call get_generation_job until terminal, or revise the stated scope.
        # Optional: While SDK is polling, periodically print the job status until the job is complete
        print("Periodically check job status:")
        while not poller.done():
            print(f"\tstatus=`{poller.status()}`")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:194

  • This loop only observes SDK-owned polling: synchronous LROPoller starts its polling thread during construction, and done()/status() do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Use polling=False, capture the initial job ID, and call get_generation_job until terminal, or revise the stated scope.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        print(f"\tstatus=`{poller.status()}`")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:172

  • This loop only observes SDK-owned polling: synchronous LROPoller starts its polling thread during construction, and done()/status() do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Use polling=False, capture the initial job ID, and call get_generation_job until terminal, or revise the stated scope.
        # Optional: While SDK is polling, periodically print the job status until the job is complete
        print("Periodically check job status:")
        while not poller.done():
            print(f"\tstatus=`{poller.status()}`")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:182

  • This loop only observes SDK-owned polling: synchronous LROPoller starts its polling thread during construction, and done()/status() do not issue application polls. It therefore does not implement the PR's stated goal of polling outside the SDK. Use polling=False, capture the initial job ID, and call get_generation_job until terminal, or revise the stated scope.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        print(f"\tstatus=`{poller.status()}`")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic.py:97

  • This changes the SDK-polling “basic” sample into another status-observation sample, even though the PR description says the basic and app-polling variants demonstrate the two distinct approaches. Keep this file as the simple blocking poller.result() example (matching its async counterpart) and leave application polling to the advanced app-polling sample.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        print(f"status=`{poller.status()}`")
        time.sleep(poll_interval)

Copilot AI review requested due to automatic review settings August 3, 2026 22:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 1 comment.

Suppressed comments (17)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:207

  • This second traces path has the same discrepancy: LROPoller is already polling in its background thread, and the loop only displays SDK state. To demonstrate application polling, disable LRO polling and explicitly retrieve the generation job on each interval.
            # Optional: While SDK is polling, periodically print the job status until the job is complete
            print("Periodically check job status:")
            while not poller.done():
                print(f"\tstatus=`{poller.status()}`")
                time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:181

  • Awaiting poller.result() delegates the entire wait to the SDK, which is the blocking behavior this PR says the dataset samples should move away from. Make this async counterpart demonstrate application polling as well (disable SDK polling, then periodically await get_generation_job), or clarify that it is intentionally the separate SDK-polling example.
        print("Waiting for the dataset generation job to complete.")
        job_result = await poller.result()

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10

  • This description is inaccurate: the code passes polling=False and polls the optimization-job resource with get_optimization_job; it does not poll a standard LRO. Describe this as application/manual polling so readers understand the distinction from the SDK-managed poller samples.
    sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78
  • The hook argument is a pipeline response, not an OptimizationJob (the next line accesses response.http_response and then constructs the model). Correcting the type description prevents users from copying an invalid hook contract.
    sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:107
  • This still delegates polling to the SDK: a synchronous LROPoller starts its background polling thread when constructed, so this loop only observes that thread. It does not restore the application-driven polling described in the PR. Disable SDK polling, retain the initial generation-job ID, and call get_generation_job on each interval, as the advanced optimization polling sample does.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        print(f"\tstatus=`{poller.status()}`")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_all_sources.py:148

  • This loop only observes the synchronous poller's SDK-owned background thread; it does not perform the application polling that the PR says these evaluator samples should demonstrate. Use polling=False, capture the initial generation-job ID, and query get_generation_job from the application loop.

This issue also appears on line 203 of the same file.

        # Optional: While SDK is polling, periodically print the job status until the job is complete
        print("Periodically check job status:")
        while not poller.done():
            print(f"\tstatus=`{poller.status()}`")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_iterate.py:102

  • This still delegates polling to the SDK: a synchronous LROPoller starts its background polling thread when constructed, so this loop only observes that thread. It does not restore the application-driven polling described in the PR. Disable SDK polling, retain the initial generation-job ID, and call get_generation_job on each interval.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        print(f"\tstatus=`{poller.status()}`")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_basic.py:126

  • This still delegates polling to the SDK: a synchronous LROPoller starts its background polling thread when constructed, so this loop only observes that thread. It does not restore the application-driven polling described in the PR. Disable SDK polling, retain the initial generation-job ID, and call get_generation_job on each interval.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        print(f"\tstatus=`{poller.status()}`")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_finetuning.py:170

  • This still delegates polling to the SDK's synchronous background thread, so it does not restore the application-driven polling described in the PR. Disable SDK polling, retain the initial data-generation job ID, and call get_generation_job on each retry interval.
                # Optional: While SDK is polling, periodically print the job status until the job is complete
                print("Periodically check job status:")
                while not poller.done():
                    print(f"\tstatus=`{poller.status()}`")
                    time.sleep(POLL_INTERVAL_SECONDS)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_traces_for_evaluation.py:167

  • This still delegates polling to the SDK's synchronous background thread, so it does not restore the application-driven polling described in the PR. Disable SDK polling, retain the initial data-generation job ID, and call get_generation_job on each retry interval.
                # Optional: While SDK is polling, periodically print the job status until the job is complete
                print("Periodically check job status:")
                while not poller.done():
                    print(f"\tstatus=`{poller.status()}`")
                    time.sleep(POLL_INTERVAL_SECONDS)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_prompt_source.py:130

  • This loop only observes SDK-managed background polling; it is not application-driven polling. To match the PR's stated purpose, submit with SDK polling disabled, retain the initial data-generation job ID, and query get_generation_job on each interval.
        # Optional: While SDK is polling, periodically print the job status until the job is complete
        print("Periodically check job status:")
        while not poller.done():
            print(f"\tstatus=`{poller.status()}`")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_file_source.py:194

  • This loop only observes SDK-managed background polling; it is not application-driven polling. To match the PR's stated purpose, submit with SDK polling disabled, retain the initial data-generation job ID, and query get_generation_job on each interval.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        print(f"\tstatus=`{poller.status()}`")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_with_agent_source.py:172

  • This loop only observes SDK-managed background polling; it is not application-driven polling. To match the PR's stated purpose, submit with SDK polling disabled, retain the initial data-generation job ID, and query get_generation_job on each interval.
        # Optional: While SDK is polling, periodically print the job status until the job is complete
        print("Periodically check job status:")
        while not poller.done():
            print(f"\tstatus=`{poller.status()}`")
            time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning.py:182

  • This loop only observes SDK-managed background polling; it is not application-driven polling. To match the PR's stated purpose, submit with SDK polling disabled, retain the initial data-generation job ID, and query get_generation_job on each interval.
    # Optional: While SDK is polling, periodically print the job status until the job is complete
    print("Periodically check job status:")
    while not poller.done():
        print(f"\tstatus=`{poller.status()}`")
        time.sleep(poll_interval_seconds)

sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:170

  • This excludes the newly added async sample from the auto-discovered sample test suite, leaving its async LRO and resource lifecycle unexecuted in CI. Add the recording and remove this exclusion before considering the sample covered.
                "sample_dataset_generation_job_simpleqna_for_finetuning_async.py",  # Need to add recordings

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:213

  • Cleanup runs only on the happy path. Any failure after uploading the seed file—file processing, LRO failure, output validation, or file retrieval—exits before these deletes and leaks Azure OpenAI files. Track created IDs and move best-effort deletion into a finally block, as the trace-generation samples do.
        for output in file_outputs:
            print(f"Delete the generated Azure OpenAI file `{output.id}`.")
            await openai_client.files.delete(file_id=output.id)

        print(f"Delete the Azure OpenAI input file `{seed_file.id}`.")

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_cancel.py:113

  • done() also becomes true when the poller's background thread terminates with an exception. Because this sample never calls wait() or result(), a transport or polling failure is silently treated as completion and the sample can print a stale non-cancelled status as success. Propagate unexpected poller exceptions and explicitly validate the expected cancelled terminal state.
    while not poller.done():
        print(f"status=`{poller.status()}`")
        time.sleep(poll_interval)

    print(f"Final LRO status: `{poller.status()}`.")

Copilot AI review requested due to automatic review settings August 3, 2026 22:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated no new comments.

Suppressed comments (4)

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling_async.py:76

  • azpysdk mypy checks this package's samples, and this empty list has no inferable element type because the nested hook's response parameter is untyped. Mypy reports var-annotated here. Restore an explicit PipelineResponse[HttpRequest, AsyncHttpResponse] element type (and the corresponding imports).
    sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10
  • This description says the sample polls the standard LRO, but the implementation sets polling=False and repeatedly calls get_optimization_job. That is application-managed polling, so the description currently teaches the opposite polling mode.

This issue also appears on line 77 of the same file.
sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78

  • response is a pipeline response, not an OptimizationJob (the next lines access response.http_response and deserialize that body). Correcting the type claim avoids misleading users implementing this hook.
    sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:170
  • This newly added async sample is explicitly removed from the auto-discovered dataset sample suite, so none of its upload, LRO, output, or cleanup paths run in CI. Please add the recording and enable the sample test before merging rather than landing the new workflow untested.
                "sample_dataset_generation_job_simpleqna_for_finetuning_async.py",  # Need to add recordings

@dargilco dargilco changed the title Restore polling in the sample in LRO operations Updates to LRO samples for Agent Optimization, Dataset Generation & Evaluator Job Aug 3, 2026
Copilot AI review requested due to automatic review settings August 4, 2026 17:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated no new comments.

Suppressed comments (6)

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:78

  • raw_response_hook receives a PipelineResponse, not an OptimizationJob; only its HTTP response body contains the job payload. The current comment gives readers the wrong callback contract.
    sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_advanced_app_polling.py:10
  • The sample disables SDK polling and explicitly calls get_optimization_job, so describing it as polling the standard LRO contradicts both the implementation and the advanced app-polling purpose. Describe the manual GET-based polling instead.

This issue also appears on line 77 of the same file.
sdk/ai/azure-ai-projects/tests/samples/test_samples_async.py:170

  • This entry excludes the only execution path for the newly added async sample from the auto-discovered sample tests. As a result, the complete async LRO flow can merge without a recording or any runtime validation; add the recording and remove this skip before merging.
                "sample_dataset_generation_job_simpleqna_for_finetuning_async.py",  # Need to add recordings

sdk/ai/azure-ai-projects/samples/evaluations/sample_rubric_evaluator_generation_lifecycle.py:122

  • Replacing the second begin_create_generation_job call with get_generation_job means this sample no longer exercises an idempotent re-submit, yet the module description and shared-job comment still claim it does, and replay_job reinforces that claim. Either restore the second begin call or rewrite those comments and rename this variable to describe retrieval.
    # Retrieve the persisted generation job using the id returned in the LRO result.
    assert evaluator.generation_job_id is not None, "Expected the generated evaluator to include a generation job id."
    replay_job = project_client.beta.evaluators.get_generation_job(evaluator.generation_job_id)
    assert replay_job.id == evaluator.generation_job_id

sdk/ai/azure-ai-projects/samples/agents/optimization/sample_optimization_job_basic_async.py:11

  • This async sample does not observe the poller until it is done; it directly awaits poller.result() and only prints the final status. Update the description to match the intentionally omitted observation loop.
    Given an async AIProjectClient, this sample demonstrates how to create an
    agent optimization job, observe the SDK poller until it is done, and then
    get the result.

sdk/ai/azure-ai-projects/samples/datasets/sample_dataset_generation_job_simpleqna_for_finetuning_async.py:129

  • Once this upload succeeds, any exception while waiting for processing, running the LRO, or inspecting outputs bypasses the cleanup block and leaves remote files behind. Track created file IDs and delete them from a finally block so the new sample cleans up on failure as well as success.
        seed_file = await openai_client.files.create(
            file=(seed_filename, io.BytesIO(SEED_REFERENCE_DOCUMENT.encode("utf-8"))),
            purpose="user_data",
        )

@dargilco
dargilco merged commit 198eb91 into main Aug 4, 2026
21 checks passed
@dargilco
dargilco deleted the dargilco/update-lro-samples branch August 4, 2026 17:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants